package com.cloudbroker.bcs.common.emoji;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by xuyn15828 on 2016/4/26.
 */
public class EmojiParser {
    private static final Pattern ALIAS_CANDIDATE_PATTERN = Pattern.compile("(?<=:)\\+?(\\w|\\||\\-)+(?=:)");
    private static final Pattern ALL_FITZPATRICK_CODES;

    private EmojiParser() {
    }

    public static String parseToAliases(String input) {
        return parseToAliases(input, EmojiParser.FitzpatrickAction.PARSE);
    }

    public static String parseToAliases(String input, EmojiParser.FitzpatrickAction fitzpatrickAction) {
        if(fitzpatrickAction == EmojiParser.FitzpatrickAction.REMOVE) {
            input = removeFitzpatrick(input);
        }

        int prev = 0;
        StringBuilder sb = new StringBuilder();
        List replacements = getUnicodeCandidates(input);
        Iterator var5 = replacements.iterator();

        while(true) {
            while(var5.hasNext()) {
                EmojiParser.UnicodeCandidate candidate = (EmojiParser.UnicodeCandidate)var5.next();
                sb.append(input.substring(prev, candidate.startIndex));
                if(fitzpatrickAction == EmojiParser.FitzpatrickAction.PARSE && candidate.emoji.supportsFitzpatrick() && candidate.fitzpatrick != null) {
                    sb.append(":").append((String)candidate.emoji.getAliases().get(0)).append("|");
                    sb.append(candidate.fitzpatrick.name().toLowerCase()).append(":");
                    prev = candidate.getEndIndexWithFitzpatrick();
                } else {
                    sb.append(":").append((String)candidate.emoji.getAliases().get(0)).append(":");
                    prev = candidate.endIndex;
                }
            }

            return sb.append(input.substring(prev)).toString();
        }
    }

    public static String parseToUnicode(String input) {
        List candidates = getAliasCandidates(input);
        String result = input;
        Iterator var3 = candidates.iterator();

        while(true) {
            EmojiParser.AliasCandidate emoji;
            Emoji emoji1;
            do {
                do {
                    if(!var3.hasNext()) {
                        Emoji emoji2;
                        for(var3 = EmojiManager.getAll().iterator(); var3.hasNext(); result = result.replace(emoji2.getHtmlDecimal(), emoji2.getUnicode())) {
                            emoji2 = (Emoji)var3.next();
                            result = result.replace(emoji2.getHtmlHexidecimal(), emoji2.getUnicode());
                        }

                        return result;
                    }

                    emoji = (EmojiParser.AliasCandidate)var3.next();
                    emoji1 = EmojiManager.getForAlias(emoji.alias);
                } while(emoji1 == null);
            } while(!emoji1.supportsFitzpatrick() && (emoji1.supportsFitzpatrick() || emoji.fitzpatrick != null));

            String replacement = emoji1.getUnicode();
            if(emoji.fitzpatrick != null) {
                replacement = replacement + emoji.fitzpatrick.unicode;
            }

            result = result.replace(":" + emoji.fullString + ":", replacement);
        }
    }

    protected static List<AliasCandidate> getAliasCandidates(String input) {
        ArrayList candidates = new ArrayList();
        Matcher matcher = ALIAS_CANDIDATE_PATTERN.matcher(input);
        matcher = matcher.useTransparentBounds(true);

        while(true) {
            while(matcher.find()) {
                String match = matcher.group();
                if(!match.contains("|")) {
                    candidates.add(new EmojiParser.AliasCandidate(match, match, (String)null));
                } else {
                    String[] splitted = match.split("\\|");
                    if(splitted.length != 2 && splitted.length <= 2) {
                        candidates.add(new EmojiParser.AliasCandidate(match, match, (String)null));
                    } else {
                        candidates.add(new EmojiParser.AliasCandidate(match, splitted[0], splitted[1]));
                    }
                }
            }

            return candidates;
        }
    }

    public static String parseToHtmlDecimal(String input) {
        return parseToHtmlDecimal(input, EmojiParser.FitzpatrickAction.PARSE);
    }

    public static String parseToHtmlDecimal(String input, EmojiParser.FitzpatrickAction fitzpatrickAction) {
        if(fitzpatrickAction != EmojiParser.FitzpatrickAction.IGNORE) {
            input = removeFitzpatrick(input);
        }

        int prev = 0;
        StringBuilder sb = new StringBuilder();
        List replacements = getUnicodeCandidates(input);

        EmojiParser.UnicodeCandidate candidate;
        for(Iterator var5 = replacements.iterator(); var5.hasNext(); prev = candidate.endIndex) {
            candidate = (EmojiParser.UnicodeCandidate)var5.next();
            sb.append(input.substring(prev, candidate.startIndex)).append(candidate.emoji.getHtmlDecimal());
        }

        return sb.append(input.substring(prev)).toString();
    }

    public static String parseToHtmlHexadecimal(String input) {
        return parseToHtmlHexadecimal(input, EmojiParser.FitzpatrickAction.PARSE);
    }

    public static String parseToHtmlHexadecimal(String input, EmojiParser.FitzpatrickAction fitzpatrickAction) {
        if(fitzpatrickAction != EmojiParser.FitzpatrickAction.IGNORE) {
            input = removeFitzpatrick(input);
        }

        int prev = 0;
        StringBuilder sb = new StringBuilder();
        List replacements = getUnicodeCandidates(input);

        EmojiParser.UnicodeCandidate candidate;
        for(Iterator var5 = replacements.iterator(); var5.hasNext(); prev = candidate.endIndex) {
            candidate = (EmojiParser.UnicodeCandidate)var5.next();
            sb.append(input.substring(prev, candidate.startIndex)).append(candidate.emoji.getHtmlHexidecimal());
        }

        return sb.append(input.substring(prev)).toString();
    }

    private static String removeFitzpatrick(String input) {
        return ALL_FITZPATRICK_CODES.matcher(input).replaceAll("");
    }

    public static String removeAllEmojis(String str) {
        str = removeFitzpatrick(str);
        int prev = 0;
        StringBuilder sb = new StringBuilder();
        List replacements = getUnicodeCandidates(str);

        EmojiParser.UnicodeCandidate candidate;
        for(Iterator var4 = replacements.iterator(); var4.hasNext(); prev = candidate.endIndex) {
            candidate = (EmojiParser.UnicodeCandidate)var4.next();
            sb.append(str.substring(prev, candidate.startIndex));
        }

        return sb.append(str.substring(prev)).toString();
    }

    public static String removeEmojis(String str, Collection<Emoji> emojisToRemove) {
        int prev = 0;
        StringBuilder sb = new StringBuilder();
        List replacements = getUnicodeCandidates(str);
        Iterator var5 = replacements.iterator();

        while(var5.hasNext()) {
            EmojiParser.UnicodeCandidate candidate = (EmojiParser.UnicodeCandidate)var5.next();
            sb.append(str.substring(prev, candidate.startIndex));
            prev = candidate.getEndIndexWithFitzpatrick();
            if(!emojisToRemove.contains(candidate.emoji)) {
                sb.append(candidate.getEmojiUnicodeWithFitzpatrick());
            }
        }

        return sb.append(str.substring(prev)).toString();
    }

    public static String removeAllEmojisExcept(String str, Collection<Emoji> emojisToKeep) {
        int prev = 0;
        StringBuilder sb = new StringBuilder();
        List replacements = getUnicodeCandidates(str);
        Iterator var5 = replacements.iterator();

        while(var5.hasNext()) {
            EmojiParser.UnicodeCandidate candidate = (EmojiParser.UnicodeCandidate)var5.next();
            sb.append(str.substring(prev, candidate.startIndex));
            prev = candidate.getEndIndexWithFitzpatrick();
            if(emojisToKeep.contains(candidate.emoji)) {
                sb.append(candidate.getEmojiUnicodeWithFitzpatrick());
            }
        }

        return sb.append(str.substring(prev)).toString();
    }

    private static List<UnicodeCandidate> getUnicodeCandidates(String input) {
        char[] inputCharArray = input.toCharArray();
        ArrayList candidates = new ArrayList();

        for(int i = 0; i < input.length(); ++i) {
            int emojiEnd = getEmojiEndPos(inputCharArray, i);
            if(emojiEnd != -1) {
                String emojiString = input.substring(i, emojiEnd);
                String fitzpatrickString = emojiEnd + 2 <= input.length()?input.substring(emojiEnd, emojiEnd + 2):null;
                candidates.add(new EmojiParser.UnicodeCandidate(emojiString, fitzpatrickString, i, emojiEnd));
                i = emojiEnd;
            }
        }

        return candidates;
    }

    private static int getEmojiEndPos(char[] text, int startPos) {
        int best = -1;

        for(int j = startPos + 1; j <= text.length; ++j) {
            EmojiTrie.Matches status = EmojiManager.isEmoji(Arrays.copyOfRange(text , startPos , j));
            if(status.exactMatch()) {
                best = j;
            } else if(status.impossibleMatch()) {
                return best;
            }
        }

        return best;
    }

    static {
        String fitzpatrickRegexString = "";
        Fitzpatrick[] var1 = Fitzpatrick.values();
        int var2 = var1.length;

        for(int var3 = 0; var3 < var2; ++var3) {
            Fitzpatrick fitzpatrick = var1[var3];
            fitzpatrickRegexString = fitzpatrickRegexString + "|" + fitzpatrick.unicode;
        }

        ALL_FITZPATRICK_CODES = Pattern.compile("(?:" + fitzpatrickRegexString.substring(1) + ")");
    }

    public static enum FitzpatrickAction {
        PARSE,
        REMOVE,
        IGNORE;

        private FitzpatrickAction() {
        }
    }

    protected static class AliasCandidate {
        public final String fullString;
        public final String alias;
        public final Fitzpatrick fitzpatrick;

        private AliasCandidate(String fullString, String alias, String fitzpatrickString) {
            this.fullString = fullString;
            this.alias = alias;
            if(fitzpatrickString == null) {
                this.fitzpatrick = null;
            } else {
                this.fitzpatrick = Fitzpatrick.fitzpatrickFromType(fitzpatrickString);
            }

        }
    }

    protected static class UnicodeCandidate {
        public final Emoji emoji;
        public final Fitzpatrick fitzpatrick;
        public final int startIndex;
        public final int endIndex;

        private UnicodeCandidate(String emoji, String fitzpatrick, int startIndex, int endIndex) {
            this.emoji = EmojiManager.getByUnicode(emoji);
            this.fitzpatrick = Fitzpatrick.fitzpatrickFromUnicode(fitzpatrick);
            this.startIndex = startIndex;
            this.endIndex = endIndex;
        }

        public String getEmojiUnicodeWithFitzpatrick() {
            return this.emoji.supportsFitzpatrick()?this.emoji.getUnicode(fitzpatrick):this.emoji.getUnicode();
        }

        public int getEndIndexWithFitzpatrick() {
            return this.fitzpatrick != null?this.endIndex + 2:this.endIndex;
        }
    }
}
